﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace CarbonExchange.Bll
{
    public class PledgeFactory : FactorySequenceBase<Pledge>
    {
        protected override void MarkItemForDeletion(Pledge item)
        {
            var tmp = item.Convert(DalContext);
            if (tmp != null)
            {
                tmp.Deleted = true;
            }
        }

        protected override void Validate(IQueryable<Pledge> items, CarbonExchange.Bll.Exceptions.ValidationException exp)
        {
            items.Validate(exp, DalContext);
        }

        protected override void PopulateDataChanges(Pledge item, object dataItem)
        {
            var tmp = dataItem as Dal.Pledge;
            if (tmp != null)
            {
                item.Id = tmp.Id;
                item.CID = tmp.CID;
                if (item.PledgeCategoryId != tmp.PledgeCategoryId)
                {
                    item.PledgeCategoryName = tmp.PledgeCategory.Name;
                }
            }
        }

        protected override object GetDataItemForUpdate(Pledge item)
        {
            return item.Convert(DalContext);
        }

        internal class JoinHelper
        {
            internal Dal.Pledge Pledge {get;set;}
            internal Dal.PledgeCategory PledgeCategory{get; set;}
        }

        private IEnumerable<JoinHelper> GetSelection()
        {
            return DalContext.Pledges.Where(x => !x.Deleted).Join(DalContext.PledgeCategories.Where(x => !x.Deleted), x => x.PledgeCategoryId, y => y.Id, (x, y) => new JoinHelper() { Pledge = x, PledgeCategory = y}).OrderBy(x => x.PledgeCategory.Section.Sequence).ThenBy(x => x.PledgeCategory.Sequence).ThenBy(x => x.Pledge.Sequence);
        }

        public IEnumerable<Pledge> GetAllByCategoryIdAndType(int categoryId, Pledge.SolutionTypes? type)
        {
            if (type != null)
            {
                return GetSelection().Where(x => x.Pledge.PledgeCategoryId == categoryId && x.Pledge.SolutionType == (byte)type).Convert();
            }
            else
            {
                return GetAllByCategoryId(categoryId);
            }
        }

        public IEnumerable<Pledge> GetAllByCategoryId(int categoryId)
        {
            return GetSelection().Where(x => x.Pledge.PledgeCategoryId == categoryId).Convert();
        }

        protected override void SetDalSequence(Pledge item, int sequence)
        {
            var tmp = DalContext.Pledges.Where(x => x.Id == item.Id && x.Sequence != sequence).SingleOrDefault();
            if (tmp != null)
            {
                tmp.Sequence = sequence;
            }
        }

        protected override void SetInitalSequence(IQueryable<Pledge> items)
        {
            var tmp = items.Where(x => x.Id == 0).ToList();
            if (tmp.Count() > 1)
            {
                foreach (var i in tmp)
                {
                    i.Sequence = tmp.IndexOf(i);
                }
            }
        }

        public Pledge GetById(int id)
        {
            return GetSelection().Where(x => x.Pledge.Id == id).SingleOrDefault().Convert();
        }

    }

    internal static class PledgeConverter
    {
        internal static Pledge Convert(this PledgeFactory.JoinHelper source)
        {
            if (source != null)
            {
                return new Pledge()
                {
                    AveSavingPerMonth = source.Pledge.AveSavingPerMonth,
                    CID = source.Pledge.CID,
                    Id = source.Pledge.Id,
                    Name = source.Pledge.Name,
                    PledgeCategoryId = source.Pledge.PledgeCategoryId,
                    PledgeCategoryName = source.PledgeCategory.Name,
                    Recommendation = source.Pledge.Recommendation,
                    SolutionType = (Pledge.SolutionTypes)source.Pledge.SolutionType,
                    Text = source.Pledge.Text,
                    Sequence = source.Pledge.Sequence
                };
            }
            else
            {
                return null;
            }
        }

        internal static IEnumerable<Pledge> Convert(this IEnumerable<PledgeFactory.JoinHelper> source)
        {
            return source.Select(x => x.Convert());
        }


        internal static Dal.Pledge Convert(this Pledge source, Dal.Context context)
        {
            if (source != null)
            {
                Dal.Pledge tmp = null;
                if (source.Id > 0)
                {
                    tmp = context.Pledges.Where(x => x.Id == source.Id && !x.Deleted).Single();
                }
                else
                {
                    tmp = new CarbonExchange.Dal.Pledge();
                    context.Pledges.InsertOnSubmit(tmp);
                }
                source.CheckConcurent(tmp.CID);
                tmp.AveSavingPerMonth = source.AveSavingPerMonth;
                tmp.PledgeCategoryId = source.PledgeCategoryId;
                tmp.Name = source.Name;
                tmp.Text = source.Text;
                tmp.Recommendation = source.Recommendation;
                tmp.SolutionType = (byte)source.SolutionType;
                return tmp;
            }
            else
            {
                return null;
            }
        }

        internal static IEnumerable<Dal.Pledge> Convert(this IEnumerable<Pledge> source, Dal.Context context)
        {
            return source.Select(x => x.Convert(context));
        }


        internal static void Validate(this IEnumerable<Pledge> source, Exceptions.ValidationException e, Dal.Context context)
        {
            foreach (var i in source)
            {
                i.Validate(e, context);
            }
        }

        internal static void Validate(this Pledge source, Exceptions.ValidationException e, Dal.Context context)
        {
        }
    }
}
